home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------------
-
- PolyPumper 1.4.2
-
- This snippet demonstrates some drawing techniques. It displays a
- bunch of colorful polygons in a window. It is based in part on
- SplatMaster by Jon Benton.
-
- Written by: Ken Long
- Updated for CW9 by: Paul Celestin
-
- 950711 - 1.0.1 - ported to CW
- 951201 - 1.0.2 - updated for CW7
- 960707 - 1.0.3 - updated for CW9
-
- ---------------------------------------------------------------------- */
-
- #include <math.h>
-
- //• --------------------------------------------------------------- •//
-
- #define ourName "\pitty bitty bytes™"
- #define keys "\pHit 'K' for Keys."
- #define w 0xffff //• Pseudo white, to save typing.
-
- //• --------------------------------------------------------------- •//
-
- Boolean singleUs = false;
- Boolean finishUs = false;
- Boolean framesUs = true;
- Boolean blacksUs = false;
- Boolean paintsUs = true;
- Boolean sticksUs = false;
- Boolean undivsUs = true;
- Boolean pausesUs = false;
- Boolean startsUs = true;
- Boolean weBeHued, weBeWaitin;
-
- EventRecord theEvent;
-
- Point middle, originalPt, nextPt;
- PolyHandle Polly; //• Grab a hold of Polly!
- Rect globWind, ourRect;
- PicHandle pict;
- Rect pictRect;
- WindowPtr pumpWindow;
- short lastSpot, radius, radius2, height;
- short divisions = 12; //• Our point total.
- long ticks;
-
- //• --------------------------------------------------------------- •//
-
- void SetForeColor (short red, short green, short blue);
- void SetBackColor (short red, short green, short blue);
- unsigned short HighLowRandom (unsigned short min, unsigned short max);
- short RangeRandom (short range);
- void GetDivisions (void);
- void GetRadii (void);
- void DrawPolygons (void);
- void SetUpWindow (void);
- void InitManagers (short numMasters);
- Boolean CheckTheEquipment (void);
- void DoSplash (void);
- void SpoutOff (void);
- void main (void);
-
- //• --------------------------------------------------------------- •//
-
- void SetForeColor(short red, short green, short blue)
- {
- RGBColor hue;
-
- hue.red = red;
- hue.green = green;
- hue.blue = blue;
-
- RGBForeColor (&hue);
- }
-
- //• --------------------------------------------------------------- •//
-
- void SetBackColor(short red, short green, short blue)
- {
- RGBColor hue;
-
- hue.red = red;
- hue.green = green;
- hue.blue = blue;
-
- RGBBackColor (&hue);
- }
-
- //• --------------------------------------------------------------- •//
-
- unsigned short HighLowRandom (unsigned short min, unsigned short max)
- {
- unsigned long ranger, tonto;
- unsigned short rawResult;
-
- rawResult = Random ();
-
- if (rawResult < 0)
- rawResult *= -1;
-
- ranger = max - min;
- tonto = (rawResult * ranger) / 65535;
- return (tonto + min);
- }
-
- //• --------------------------------------------------------------- •//
-
- short RangeRandom (short range)
- {
- long rawResult;
-
- rawResult = Random ();
-
- if (rawResult < 0)
- rawResult *= - 1;
-
- return ((rawResult * range) / 32768);
- }
-
- void GetDivisions ()
- {
- //• Total points, inner plus outer.
- //• Anywhere between 0 and 100.
- //• I could have used "HighLowRandom (4, 100);" instead! :^)
- divisions = RangeRandom(100);
-
- //• Divisions must be even, so I rigged up a phoney "odd"
- //• handler. If divisions was 9, half of that is 4.5, rounded
- //• up would be 5.
- if (divisions != ceil((divisions / 2) * 2))
- divisions++;
- }
-
- void GetRadii ()
- {
- //• This radius only gets positive values...
- radius = RangeRandom(height);
-
- //• ...but this one gets positive and negative, so the
- //• polygon points can lap, giving the "holey" effect.
- radius2 = HighLowRandom (- height, height);
- }
-
- //• --------------------------------------------------------------- •//
- //• The main action proc, where the magic takes place.
- void DrawPolygons ()
- {
- short i;
- double thetaStep, theta;
-
- //• Screen center is the start point.
- middle.h = (qd.thePort->portRect.right / 2);
- middle.v = (qd.thePort->portRect.bottom / 2);
-
- //• The height of our overall draw area.
- height = pumpWindow->portRect.bottom / 2 - 4;
-
- if (! undivsUs)
- GetDivisions ();
-
- //• Less than 4 looks funky.
- if (divisions < 4)
- divisions = 4;
-
- if (! sticksUs)
- GetRadii ();
-
- //• Some circle math thing...
- thetaStep = (2 * 3.14159) / divisions;
- theta = 0;
-
- //• Start recording polygon points.
- Polly = OpenPoly ();
-
- //• SetPt handles .h and .v (cool). Notice no need to
- //• initialize "originalPt" before this? The values are
- //• calc'd off the already established "radius" value.
- SetPt(&originalPt, radius * cos (theta),
- radius * sin (theta));
-
- //• Then we move to center, plus that "SetPt" value.
- //• This is a horzontal offset from center, so our polygons
- //• will be "laying on their sides" if half of divisons
- //• is odd.
- MoveTo(middle.h + originalPt.h, middle.v + originalPt.v);
-
- //• Now that we have a start point, we go from there, around
- //• the circle, for the number of divisions, which we made an
- //• even total.
- for (i = 0; i < divisions; i++)
- {
- //• But, there are odd and even numbers in the sequence.
- //• We want odd to be one radius and even to be the other.
- //• So we jockey back and forth using the index as a guide.
- if (i == ceil (i / 2) * 2)
- SetPt(&nextPt, radius * cos (theta),
- radius * sin (theta));
- else
- SetPt(&nextPt, radius2 * cos (theta),
- radius2 * sin (theta));
-
- //• Some other circle/math thing. How far around?
- theta += thetaStep;
-
- //• Still in our loop, we record where the poly point
- //• is, off the center, to the point we just set.
- LineTo(middle.h + nextPt.h, middle.v + nextPt.v);
- }
- //• Finally, we close the polygon with a line back to the
- //• point we started at.
- LineTo(middle.h + originalPt.h, middle.v + originalPt.v);
-
- //• Then stop recording.
- ClosePoly ();
-
- //• Now set a color to paint the polygon with, and paint it
- //• *IF* we're painting.
- if (paintsUs == true)
- {
- SetForeColor (Random (), Random (), Random ());
- PaintPoly (Polly);
- }
-
- //• Then set the forecolor to black for the frame
- //• *IF* we're framing.
- if (framesUs == true)
- {
- SetForeColor (0, 0, 0);
- FramePoly (Polly);
- }
-
- //• Now dump all the memory this took,
- //• since the pixels are now ON the screen!
- KillPoly (Polly);
- }
-
- //• --------------------------------------------------------------- •//
- //• "Cheapo" window, but it works! Set to srceen edges.
- void SetUpWindow (void)
- {
- HideMenuBar (); //• Do this while we're here.
- pumpWindow = NewCWindow (0L, &qd.screenBits.bounds, "\p", true,
- plainDBox, (WindowPtr) -1L, true, 0);
- SetPort (pumpWindow);
- HideCursor (); //• Swat the fly, too.
- DoSplash (); //• Do some heavy bragging.
- }
-
- //• --------------------------------------------------------------- •//
-
- void InitManagers (short numMasters)
- {
- short i;
- //• The manager's names:
- InitGraf (&qd.thePort); //• Quick Draw McGraw.
- InitFonts (); //• Alfonso
- InitWindows (); //• Windex.
- TEInit (); //• Te he he.
- InitDialogs (((void *) 0)); //• Paul Bunion (lumberjack).
-
- for (i = 0; i < 5; i++)
- {
- MoreMasters ();
- }
- FlushEvents (everyEvent, 0);
- InitCursor (); //• Watch your language!
- }
-
- //• --------------------------------------------------------------- •//
- //• A hold-over from where I got it (SplatMaster).
- //• Mainly check for color is what we want.
- Boolean CheckTheEquipment (void)
- {
- #define versRequested 1 //• This is a 68000
- #define The_Wait_Trap 0x60
- #define Unimpl_Pimple 0x9f
-
- OSErr err;
- SysEnvRec theWorld; //• Wrecking the world?
- Boolean runability = false; //• Got legs?
-
- weBeHued = false;
-
- err = SysEnvirons(versRequested, &theWorld);
-
- //• Fi this is a 68000 Mac, we skip to _L99 with runability false.
- if (err != noErr)
- goto _L99; //• The dreaded "goto." Actually useful.
-
- //• If there was no error in the "noErr", we read this.
- //• _L99, runability still false, on a MacSE.
- if (theWorld.machineType <= 3)
- goto _L99;
-
- //• If the machineType was okay, we read this.
- if (theWorld.hasColorQD)
- weBeHued = true; //• Huey To-us and the News!
-
- //• If we made it this far...
- runability = true; //• Doesn't apply to Ross Perot.
-
- //• Why do this? We're using "GetNextEvent!" Leftovers.
- weBeWaitin = (NGetTrapAddress(The_Wait_Trap, ToolTrap) !=
- NGetTrapAddress(Unimpl_Pimple, ToolTrap));
-
- _L99:
- if (runability)
- return true;
- }
-
- //• --------------------------------------------------------------- •//
- void DoSplash () //• Much ado over nothing!
- {
- short pR, pB, sR, sB, L, T, R, B; //• Some stuff to save typing
- //• in our SetRect call :^)
- pict = GetPicture (128);
-
- if (pict != 0L)
- {
- pR = (**pict).picFrame.right;
- pB = (**pict).picFrame.bottom;
- sR = pumpWindow->portRect.right;
- sB = pumpWindow->portRect.bottom;
- L = sR / 2 - pR / 2;
- T = sB / 2 - pB / 2;
- R = L + pR;
- B = T + pB;
- SetRect (&pictRect, L, T, R, B);
- DrawPicture (pict, &pictRect);
- ReleaseResource ((Handle) pict);
- }
- while (! Button ()) //• If we ain't clickin'...
- ; //• we keeps on stickin'!
-
- EraseRect (&pictRect);
- if (startsUs)
- {
- DoInstructions ();
- startsUs = false;
- }
- SpoutOff (); //• Put this up, initially.
- }
-
- //• --------------------------------------------------------------- •//
- DoInstructions ()
- {
- pict = GetPicture (129);
- EraseRect (&pumpWindow->portRect);
-
- if (pict != 0L)
- {
- DrawPicture (pict, &pictRect);
- ReleaseResource ((Handle) pict);
- }
- while (! Button ()) //• If we ain't clickin'...
- ; //• we keeps on stickin'!
- EraseRect (&pictRect);
- SpoutOff ();
- }
-
- // Str255 s00 = "\pSINGLE KEY CONTROLS:",
- // s01 = "\p+........Increase divisions by two.",
- // s02 = "\p-........Decrease divisions by two.",
- // s03 = "\p*........Pause or not.",
- // s04 = "\pB........White or black background.",
- // s05 = "\pD........Divisons random or not.",
- // s06 = "\pE........Erase window once.",
- // s07 = "\pF........Frame polygon or not.",
- // s08 = "\pI........Show these instructions again.",
- // s09 = "\pP........Paint polygon or not.",
- // s10 = "\pR........Radii random or not.",
- // s11 = "\pS........Erase window after 1 second delay, or not.",
- // s12 = "\pQ........Quit.",
- // s13 = "\pCLICK TO EXIT INSTRUCTIONS";
- //
- // //• Wipe the slate and put up instructions.
- // EraseRect (&pumpWindow->portRect);
- // Delay (20L, &ticks);
- // MoveTo (20, 40); DrawString (s00);
- // MoveTo (20, 60); DrawString (s01);
- // MoveTo (20, 80); DrawString (s02);
- // MoveTo (20, 100); DrawString (s03);
- // MoveTo (20, 120); DrawString (s04);
- // MoveTo (20, 140); DrawString (s05);
- // MoveTo (20, 160); DrawString (s06);
- // MoveTo (20, 180); DrawString (s07);
- // MoveTo (20, 200); DrawString (s08);
- // MoveTo (20, 220); DrawString (s09);
- // MoveTo (20, 240); DrawString (s10);
- // MoveTo (20, 260); DrawString (s11);
- // MoveTo (20, 280); DrawString (s12);
- // MoveTo (20, 320); DrawString (s13);
- // while (! Button ())
- // ;
- // //• Wipe the slate and on with the show!
- // EraseRect (&pumpWindow->portRect);
- //}
-
- //• --------------------------------------------------------------- •//
- //• Brag a little, and let user know how to get out, etc.
- void SpoutOff ()
- {
- SetForeColor (w / 2, w / 2, w / 2);
-
- MoveTo (5, pumpWindow->portRect.bottom - 5);
- DrawString (keys);
- MoveTo (pumpWindow->portRect.right - StringWidth (ourName) - 5,
- pumpWindow->portRect.bottom - 5);
- DrawString (ourName);
- }
-
- //• --------------------------------------------------------------- •//
-
- void main ()
- {
- short chCode;
- char theKey;
- unsigned long myRand = qd.randSeed;
-
- GetDateTime (&myRand);
-
- InitManagers (5);
- if (CheckTheEquipment()) //• Find out about our environment.
- {
- SetUpWindow ();
- do
- {
- if (GetNextEvent(everyEvent, &theEvent))
- switch (theEvent.what)
- {
- case keyDown:
- chCode = (theEvent.message & charCodeMask);
- //• These key hits are self explanatory.
- switch (chCode)
- {
- case 'b':
- if (blacksUs == false)
- {
- SetBackColor (w, w, w);
- EraseRect (&pumpWindow->portRect);
- }
- else
- {
- SetBackColor (0, 0, 0);
- EraseRect (&pumpWindow->portRect);
- }
- SpoutOff ();
- blacksUs = ! blacksUs;
- break;
-
- case 'd':
- undivsUs = ! undivsUs;
- break;
-
- case 'a': //• Wipe.
- EraseRect (&pumpWindow->portRect);
- DoSplash (); //• Put this back.
- break;
-
- case 'c': //• Wipe.
- EraseRect (&pumpWindow->portRect);
- SpoutOff (); //• Put this back.
- break;
-
- case 'f':
- framesUs = ! framesUs;
- break;
-
- case 'k':
- DoInstructions ();
- //• Flush in case user hit 'i' again.
- FlushEvents (everyEvent, 0);
- SpoutOff ();
- break;
-
- case 'p':
- paintsUs = ! paintsUs;
- break;
-
- case 'q':
- finishUs = true;
- break;
-
- case 'r':
- sticksUs = ! sticksUs;
- break;
-
- case 's':
- singleUs = ! singleUs;
- break;
-
- case '+':
- divisions += 2;
- break;
-
- case '-':
- divisions -= 2;
- break;
-
- case '*':
- pausesUs = ! pausesUs;
- break;
- }
- break;
-
- //• It does this every time, unless something
- //• changes.
- default:
- //• Do this *IF* single is true and
- //• pausing is false.
- if ((singleUs) && (! pausesUs))
- {
- DrawPolygons ();
- Delay (59L, &ticks);
- EraseRect (&pumpWindow->portRect);
- SpoutOff ();
- }
- //• Otherwise just draw, unless paused.
- if ((! singleUs) && (! pausesUs))
- DrawPolygons ();
- break;
- }
- }while (! finishUs); //• 'q' key sets us free.
- }
- ShowMenuBar (); //• This would probably happen anyway, but...
- InitCursor ();
- }
-
- //• --------------------------------------------------------------- •//
-
- //• We're outta here!